#include "db.h"
#include "user.h"

#include <iostream>
#include <fstream>


std::vector<User*>           db::m_users;
std::map<int, User*>         db::m_users_by_id;
std::map<std::string, User*> db::m_users_by_username;
unsigned int                 db::m_current_user_id;

bool db::initialize()
{

  unsigned int id;
  char name[256];
  char password[256];
  char firstname[256];
  char lastname[256];
  time_t joined;
  bool active;


  m_current_user_id = 0;


  std::ifstream is("users.txt");
  if (is.is_open())
  {
    while (!is.eof())
    {
      is >> id;
      if (is.eof())
        break;
      is >> name;
      is >> password;
      is >> firstname;
      is >> lastname;
      is >> joined;
      is >> active;

      User * u = new User(id, name, password, firstname, lastname, joined, active);
      m_users.push_back(u);

      if (id >= m_current_user_id)
        m_current_user_id = id + 1;

      m_users_by_id[id] = u;
      m_users_by_username[u->getUsername()] = u;
    }

    is.close();
  }

  return true;


}

bool db::finalize()
{

  writeUsers();

  for (unsigned int i = 0; i < m_users.size(); i++)
  {
    delete m_users[i];
  }

  return true;

}



void db::notifyChange(User * user)
{
  // normally this would register change and then the tread would deal with pushing modifications to permanent storage, but for now just dump all users to file :D

  //dirty
  writeUsers();

}

void db::writeUsers()
{

  using namespace std;

  std::ofstream os("users.txt");

  if (os.is_open())
  {
    std::cout << "stream opened" << m_users.size() << std::endl;
    for (unsigned int i = 0; i < m_users.size(); i++)
    { 
      os << m_users[i]->getId() << std::endl;;
      os << m_users[i]->getUsername() << endl;
      os << m_users[i]->getPassword() << endl;
      os << m_users[i]->getFirstName() << endl;
      os << m_users[i]->getLastName() << endl;
      os << m_users[i]->getJoined() << endl;
      os << m_users[i]->getActive() << endl;
    }

    os.close();
    std::cout << "write complete" << std::endl;
  }
  else
  {
    std::cout << "cannot write out" << std::endl;
  } 
}

void db::insertUser(User * u)
{
  u->setId(m_current_user_id);
  m_current_user_id++;
  m_users.push_back(u);
  m_users_by_id[u->getId()] = u;
  m_users_by_username[u->getUsername()] = u;
  

}

User * db::getUserById(int id)
{
  std::map<int, User*>::iterator it;
  it = m_users_by_id.find(id);
  if (it == m_users_by_id.end())
    return 0;
  else
    return it->second;

}

User * db::getUserByUsername(const std::string& name)
{ 
  std::map<std::string, User*>::iterator it;
  it = m_users_by_username.find(name);
  if (it == m_users_by_username.end())
    return 0;
  else
    return it->second;
}
